﻿using System;
using System.Runtime.InteropServices;
using System.Windows.Controls;
using EnvDTE;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell;
using TskComment.ViewModel;

namespace TskComment
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : UserControl
    {
        IOleComponentManager manager;
        private uint componentCookie;
        OleComponent component;
        OLECRINFO regInfo;

        public MainWindow(DTE dte)
        {
            InitializeComponent();
            ((MainViewModel)this.DataContext).DTE = dte;

            //---------- 以下代码用于纠正在 MainWindow 上点击 backspace、delete、箭头按键时不能响应-----------------
            //详见 https://connect.microsoft.com/VisualStudio/feedback/details/549866/msdn-visual-studio-extensibility-forum-backspace-tab-and-enter-key-are-not-captured-in-wpf-window-which-exist-in-a-package#details
            cmtCol.GotKeyboardFocus += GotKeyboardFocus;
            cmtCol.LostKeyboardFocus += LostKeyboardFocus;

            component = new OleComponent();
            regInfo = new OLECRINFO() { grfcrf = 0U, grfcadvf = 0U, uIdleTimeInterval = 0U };
            regInfo.cbSize = (uint)Marshal.SizeOf(regInfo);

            ServiceProvider serviceProvider = new ServiceProvider((Microsoft.VisualStudio.OLE.Interop.IServiceProvider)dte);
            manager = serviceProvider.GetService(typeof(SOleComponentManager)) as IOleComponentManager;
            if (manager == null)
            {
                throw new InvalidOperationException("Could not retrieve the IOleComponentManager");
            }
        }

        void GotKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
        {
            int result = manager.FRegisterComponent(component, new OLECRINFO[] { regInfo }, out componentCookie);
            if (!ErrorHandler.Succeeded(result))
            {
                throw new InvalidOperationException("Could not register the OleComponent");
            }

            manager.FOnComponentActivate(componentCookie);
        }

        void LostKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
        {
            manager.FRevokeComponent(componentCookie);
        }

        /// <summary>
        /// The default IOleComponent for Visual Studio will translate keystrokes into
        /// commands for the active IVsWindowFrame.  By activating this component when this window is active,
        /// it will allow normal keyboard processing without command keybindings.
        /// </summary>
        class OleComponent : IOleComponent
        {
            public int FContinueMessageLoop(uint uReason, IntPtr pvLoopData, MSG[] pMsgPeeked)
            {
                return VSConstants.S_OK;
            }

            public int FDoIdle(uint grfidlef)
            {
                return VSConstants.S_OK;
            }

            public int FPreTranslateMessage(MSG[] pMsg)
            {
                return VSConstants.S_OK;
            }

            public int FQueryTerminate(int fPromptUser)
            {
                return VSConstants.S_FALSE;
            }

            public int FReserved1(uint dwReserved, uint message, IntPtr wParam, IntPtr lParam)
            {
                return VSConstants.S_OK;
            }

            public IntPtr HwndGetWindow(uint dwWhich, uint dwReserved)
            {
                return IntPtr.Zero;
            }

            public void OnActivationChange(IOleComponent pic, int fSameComponent, OLECRINFO[] pcrinfo, int fHostIsActivating, OLECHOSTINFO[] pchostinfo, uint dwReserved)
            {
            }

            public void OnAppActivate(int fActive, uint dwOtherThreadID)
            {
            }

            public void OnEnterState(uint uStateID, int fEnter)
            {
            }

            public void OnLoseActivation()
            {
            }

            public void Terminate()
            {
            }
        }
    }
}
